home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / lantimes / 90_03 / tnet.c < prev    next >
C/C++ Source or Header  |  1990-01-08  |  16KB  |  554 lines

  1. /*-------------------------------------------------------------------------*
  2.  * tnet.c -- network client application
  3.  *
  4.  * The main routine establishes communications with the
  5.  * tnet ``server,'' then accepts commands from the user.
  6.  * Each command is then serviced by one of the ``cmd_xxx()''
  7.  * routines below.
  8.  *
  9.  * T. Nolan - 11/20/89
  10.  *-------------------------------------------------------------------------*/
  11.  
  12. #include <dos.h>
  13. #include <process.h>
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <time.h>
  18.  
  19. #include "netbios.h"
  20. #include "network.h"
  21.  
  22. #define NARGS 10        /* max number of command arguments */
  23.  
  24. int exitflag;
  25. char local[16];            /* node name of local machine */
  26. char remote[16];        /* node name of remote server */
  27. char buf[4096];            /* buffer for file read/write */
  28.  
  29. extern int nb_errno;       /* netbios error return */
  30.  
  31. /*-------------------------------------------------------------------------*/
  32. main(int ac, char **av)
  33. {
  34.    ACTION ncmd, rcmd;   /* send and receive cmd blocks   */
  35.    NCB    ncb;             /* NetBIOS ncb                   */
  36.    long   ltime;           /* for timeout                   */
  37.    char   *argv[NARGS];    /* array of parsed command args  */
  38.    int    argc;            /* number of command args        */
  39.    char   line[80];        /* buffer for command line       */
  40.  
  41.    printf("Tnet - T. Nolan 11/20/89\n");
  42.  
  43.    /* Post a receive-datagram, and send out a connect request.
  44.     * Use the command-line arg as the server node name and
  45.     * request via datagram. Set a 5-second timeout, and wait for
  46.     * something to happen.
  47.     */
  48.  
  49.    if(ac == 1)
  50.    {
  51.       printf("Format is TNET \\\\nodeid");
  52.       exit(1);
  53.    }
  54.  
  55.    clear_ncb(&ncb);
  56.    nw_recv_datagram(&rcmd, sizeof(ACTION), &ncb);
  57.    ncmd.type = NET_CNCT;
  58.    ncmd.code = 0;
  59.    while(1)
  60.    {
  61.       time(<ime);
  62.       printf("Trying to locate Tnet server...\n");
  63.       strcpy(remote, av[1]);
  64.       send_datagram(remote, &ncmd, sizeof(ACTION));
  65.  
  66.       while((time(0) < ltime + 5) && !kbhit() && (ncb.cmdcplt == 0xff))
  67.          ;
  68.  
  69.       /* Figure out what happened. */
  70.  
  71.       if(kbhit())       /* keyboard interrupt */
  72.       {
  73.          if(!getch())
  74.             getch();
  75.          nb_cancel(&ncb);
  76.          exit(1);
  77.       }
  78.  
  79.       if(ncb.cmdcplt != 0xff)            /* command completed */
  80.       {
  81.          if(ncb.retcode)
  82.          {
  83.             printf("NetBIOS error %x\n", ncb.retcode);
  84.             exit(1);
  85.          }
  86.          if(rcmd.type != NET_CNCT || rcmd.code != NET_ACK)
  87.          {
  88.             printf("NetBIOS not installed\n");
  89.             exit(1);
  90.          }
  91.          break;      /* exit from loop */
  92.       }
  93.    }           /* must have timed out.. try again */
  94.  
  95.    /* If we get here, we've had a successful datagram exchange
  96.     * with the server. The server's node name appears in
  97.     * the ncb, and our node name appears in the rcmd.
  98.     */
  99.  
  100.    namecpy(remote, ncb.callname);
  101.    namecpy(local, rcmd.name);
  102.  
  103.    printf("\Tnet node %s connected to server node %s\n", local, remote);
  104.  
  105.    /* Command loop. Write the prompt, get a command. Split
  106.     * the command into its component strings and tokenize
  107.     * the command name. Invoke the appropriate handler.
  108.     */
  109.  
  110.    while(!exitflag)
  111.    {
  112.       printf("\nTnet> ");     /* prompt user for command */
  113.       gets(line);       /* read command line */
  114.       argc = reargv(strlwr(line), argv); /* separate arguments */
  115.       if(!argc)
  116.          continue;      /* nothing to do... */
  117.       if(*argv[0] == '!')     /* "shell out" prefix */
  118.       {
  119.          argv[0]++;
  120.          shell(argc, argv);
  121.          continue;
  122.       }
  123.  
  124.       switch(parse(argv[0]))     /* look at 1st arg */
  125.       {
  126.          case -1 :
  127.  
  128.             printf("Ambiguous command\n");
  129.             cmd_help();
  130.             break;
  131.  
  132.          case 0 :
  133.  
  134.             cmd_remote(argc, argv);
  135.             break;
  136.  
  137.          case 1 :
  138.  
  139.             cmd_get (argc, argv);
  140.             break;
  141.  
  142.          case 2 :
  143.  
  144.             cmd_put (argc, argv);
  145.             break;
  146.  
  147.          case 3 :
  148.  
  149.             cmd_chd (argc, argv);
  150.             break;
  151.  
  152.          case 4 :
  153.  
  154.             cmd_help(argc, argv);
  155.             break;
  156.  
  157.          case 5 :
  158.  
  159.             cmd_bye (argc, argv);
  160.             break;
  161.  
  162.          case 6 :
  163.  
  164.             cmd_dir (argc, argv);
  165.             break;
  166.  
  167.          case 7 :
  168.          case 8 :
  169.  
  170.             cmd_del (argc, argv);
  171.             break;
  172.  
  173.          case 9 :
  174.  
  175.             exitflag = 1;
  176.             break;
  177.       }
  178.    }
  179.    exit(0);
  180. }
  181.  
  182. /*-------------------------------------------------------------------------*/
  183. int reargv(char *cmd, char **av)    /* turn command line into argc, argv[] */
  184. {
  185.    int c;
  186.    int inwhite = 1;
  187.    int ac;
  188.  
  189.    /* This is a simple lexical scanner that looks for
  190.     * white space separating command arguments. Each
  191.     * argument found is terminated by a null byte. The
  192.     * count and the array of arguments are returned.
  193.     */
  194.  
  195.    for(ac = 0; ac < NARGS; ac++)    /* zero all arg pointers */
  196.       av[ac] = '\0';
  197.    ac = 0;           /* zero arg count */
  198.  
  199.    while(*cmd)       /* scan the command line */
  200.    {
  201.       if(inwhite && *cmd != ' ') /* found the start of a word... */
  202.       {
  203.          inwhite = 0;
  204.          av[ac++] = cmd;      /* ...so set the next arg pointer */
  205.       }
  206.       else if(!inwhite && *cmd == ' ') /* found end of a word... */
  207.       {
  208.          inwhite = 1;
  209.          *cmd = '\0';   /* ...so null-terminate it */
  210.       }
  211.       cmd++;
  212.    }
  213.    return(ac);       /* return count of args found */
  214. }
  215.  
  216. /*-------------------------------------------------------------------------*/
  217. int parse(char *cmd)                          /* tokenize the command word */
  218. {
  219.    /* This tokenizer finds a command in the table matching the
  220.     * given string, and returns its index in the table. It
  221.     * returns 0 if no match is found. Abbreviated commands
  222.     * are accepted, and -1 is returned if the string matches
  223.     * more than one command.
  224.     */
  225.    static char *cmd_table[] =
  226.    {
  227.       "get",    /* 1 */
  228.       "put",    /* 2 */
  229.       "cd",     /* 3 */
  230.       "help",   /* 4 */
  231.       "kill",   /* 5 */
  232.       "dir",    /* 6 */
  233.       "del",    /* 7 */
  234.       "erase",  /* 8 */
  235.       "quit",   /* 9 */
  236.       0
  237.    };
  238.  
  239.    int i = 0;
  240.    int match = -1;
  241.    char **cp = cmd_table;
  242.  
  243.    while(*cp)                       /* loop through the cmd table */
  244.    {
  245.       i++;
  246.       if(!strncmp(*cp, cmd, strlen(cmd)))
  247.       {
  248.          if(match != -1)
  249.             return(-1);          /* ambiguous command */
  250.          else
  251.             match = i;           /* set match index */
  252.       }
  253.       cp++;
  254.    }
  255.  
  256.    if(match == -1)
  257.       return(0);                 /* no match */
  258.    else
  259.       return(match);             /* successful match */
  260. }
  261.  
  262. /*-------------------------------------------------------------------------*/
  263. cmd_get(int ac, char **av)                   /* get files from server */
  264. {
  265.    ACTION ncmd, rcmd;
  266.    NCB   ncb;
  267.    int len;
  268.    int lsn = 0;
  269.    FILE *fp;
  270.    long size;
  271.  
  272.    if(ac < 2)
  273.    {
  274.       printf("error - no file name supplied\n");
  275.       return;
  276.    }
  277.  
  278.    ncmd.type = NET_GET;
  279.    ncmd.code = 0;
  280.    strcpy(ncmd.name, av[1]);
  281.    clear_ncb(&ncb);           /* post 1st receive */
  282.    nw_recv_datagram(&rcmd, sizeof(ACTION), &ncb);
  283.    send_datagram(remote, &ncmd, sizeof(ACTION));   /* send our request */
  284.  
  285.    while(1)
  286.    {
  287.       while(ncb.cmdcplt == 0xff)
  288.          ;
  289.       if(rcmd.code == NET_ERR)      /* no more files */
  290.          break;            /* ..so get out */
  291.  
  292.       if(!lsn)
  293.          lsn = listen(remote, local);  /* establish session */
  294.                      /* (1st time only)   */
  295.       size = rcmd.size;       /* save file size */
  296.       printf("file %s", rcmd.name);
  297.       fp = fopen(rcmd.name, "wb");     /* open it */
  298.       while(size > 0)            /* get the data */
  299.       {
  300.          printf(".");
  301.          len = receive(lsn, buf, sizeof(buf));
  302.          if(fp)
  303.             fwrite(buf, 1, len, fp);
  304.          size -= len;
  305.       }
  306.  
  307.       size = rcmd.size;       /* save size again */
  308.       clear_ncb(&ncb);        /* post next receive */
  309.       nw_recv_datagram(&rcmd, sizeof(ACTION), &ncb);
  310.       send(lsn, 0, 0);        /* ACK this file */
  311.       if(fp)
  312.       {
  313.          printf(" %ld bytes received.\n", size);
  314.          fclose(fp);
  315.       }
  316.       else
  317.          printf(" error opening file.\n");
  318.    }                 /* loop for more */
  319.    hangup(lsn);
  320. }
  321.  
  322. /*-------------------------------------------------------------------------*/
  323. cmd_put(int ac, char **av)              /* put files to remote server */
  324. {
  325.    ACTION ncmd;
  326.    NCB ncb;
  327.    FILE *fp;
  328.    int lsn = 0;
  329.    int len;
  330.    struct find_t info;
  331.    int found;
  332.    long size;
  333.    char fname[80];
  334.    char *dir_end;
  335.  
  336.    if(ac < 2)
  337.    {
  338.       printf("error - no file spec supplied\n");
  339.       return;
  340.    }
  341.  
  342.    strcpy(fname, av[1]);         /* copy file specification */
  343.    dir_end = strrchr(fname, '\\');     /* locate last '\' char */
  344.    if(!dir_end)            /* none there, so */
  345.       dir_end = fname;     /* no directory string */
  346.    else              /* found one, so */
  347.       dir_end++;        /* point one char past it */
  348.  
  349.    /* find matching file in current working directory */
  350.  
  351.    found = !_dos_findfirst(av[1], _A_NORMAL, &info);
  352.    while(found)                               /* do for all matching files */
  353.    {
  354.       *dir_end = '\0';                        /* prepare to concatenate */
  355.       strcat(fname, info.name);               /* file name onto dir string */
  356.       if((fp = fopen(fname, "rb")) == NULL)   /* open file */
  357.          break;
  358.       ncmd.size = size = info.size;           /* extract file size */
  359.       strcpy(ncmd.name, info.name);           /* copy to cmd blk */
  360.       ncmd.type = NET_PUT;
  361.       ncmd.code = 0;
  362.       clear_ncb(&ncb);                        /* issue a receive */
  363.       nw_recv_datagram(&ncmd, sizeof(ACTION), &ncb);
  364.       send_datagram(remote, &ncmd, sizeof(ACTION));   /* req put */
  365.       while(ncb.cmdcplt == 0xff)              /* wait for receive */
  366.          ;
  367.       printf("file %s", fname);
  368.       if(ncmd.code == NET_ERR)                /* req rejected */
  369.       {
  370.          printf(" error sending file\n");
  371.          continue;         /* skip this one */
  372.       }
  373.       lsn = listen(remote, local);     /* establish session */
  374.  
  375.       while(size > 0)            /* send the data */
  376.       {
  377.          printf(".");
  378.          len = fread(buf, 1, sizeof(buf), fp);
  379.          send(lsn, buf, len);
  380.          size -= len;
  381.       }
  382.       receive(lsn, 0, 0);                            /* wait for hangup */
  383.       fclose(fp);                                    /* close file */
  384.       printf(" %ld bytes sent.\n", info.size);
  385.       found = !_dos_findnext(&info);                 /* find next file */
  386.    }
  387. }
  388.  
  389. /*-------------------------------------------------------------------------*/
  390. cmd_chd(int ac, char **av)                      /* change remote directory */
  391. {
  392.    ACTION ncmd;
  393.    NCB ncb;
  394.  
  395.    ncmd.type = NET_CHD;
  396.    ncmd.code = 0;
  397.    strcpy(ncmd.name, av[1]);
  398.    clear_ncb(&ncb);
  399.    nw_recv_datagram(&ncmd, sizeof(ACTION), &ncb);    /* post receive */
  400.    send_datagram(remote, &ncmd, sizeof(ACTION));     /* send chd req */
  401.    while(ncb.cmdcplt == 0xff)                        /* wait for recv */
  402.       ;
  403.    if(ncmd.code != NET_ACK)                          /* check for error */
  404.       printf("directory or drive not found\n");
  405.    printf("current directory is %s\n", ncmd.name);   /* print cwd */
  406. }
  407.  
  408. /*-------------------------------------------------------------------------*/
  409. cmd_dir(int ac, char **av)                /* remote directory listing */
  410. {
  411.    ACTION ncmd;
  412.    NCB ncb;
  413.    int lsn;
  414.    int len;
  415.  
  416.    ncmd.type = NET_DIR;
  417.    ncmd.code = 0;
  418.    strcpy(ncmd.name, av[1]);
  419.  
  420.    clear_ncb(&ncb);
  421.    nw_recv_datagram(&ncmd, sizeof(ACTION), &ncb);  /* post receive */
  422.    send_datagram(remote, &ncmd, sizeof(ACTION));   /* send dir request */
  423.    while(ncb.cmdcplt == 0xff)       /* wait for recv */
  424.       ;
  425.    if(ncmd.code != NET_ACK)         /* check for error */
  426.    {
  427.       printf("error getting directory\n");
  428.       return;
  429.    }
  430.  
  431.    lsn = listen(remote, local);        /* establish session */
  432.  
  433.    while(ncmd.size > 0)          /* receive dir list */
  434.    {
  435.       len = receive(lsn, buf, sizeof(buf));
  436.       fwrite(buf, 1, len, stdout);     /* put to screen */
  437.       ncmd.size -= len;
  438.    }
  439.    hangup(lsn);               /* hang up session */
  440. }
  441.  
  442. /*-------------------------------------------------------------------------*/
  443. cmd_del(int ac, char **av)                     /* delete remote files */
  444. {
  445.    ACTION ncmd;
  446.    NCB    ncb;
  447.  
  448.    if(ac < 2)
  449.    {
  450.       printf("error - no file specified\n");
  451.       return;
  452.    }
  453.  
  454.    ncmd.type = NET_DEL;
  455.    ncmd.code = 0;
  456.    strcpy(ncmd.name, av[1]);
  457.    clear_ncb(&ncb);
  458.    nw_recv_datagram(&ncmd, sizeof(ACTION), &ncb);  /* post receive */
  459.    send_datagram(remote, &ncmd, sizeof(ACTION));   /* send del request */
  460.    while(ncb.cmdcplt == 0xff)       /* wait for recv */
  461.       ;
  462.    printf("%d files deleted\n", ncmd.size);  /* print information */
  463. }
  464.  
  465. /*-------------------------------------------------------------------------*/
  466. cmd_remote(int ac, char **av)             /* execute a remote command */
  467. {
  468.    ACTION ncmd;
  469.    NCB    ncb;
  470.    char   *bp;
  471.  
  472.    ncmd.type = NET_REMOTE;
  473.    ncmd.code = 0;
  474.    ncmd.size = ac;                         /* number of args in cmd */
  475.    for(bp = ncmd.name; ac; --ac, ++av)     /* copy the rest of the args */
  476.    {
  477.       strcpy(bp, *av);
  478.       bp += strlen(*av) + 1;
  479.    }
  480.  
  481.    clear_ncb(&ncb);
  482.    nw_recv_datagram(&ncmd, sizeof(ACTION), &ncb);  /* post receive */
  483.    send_datagram(remote, &ncmd, sizeof(ACTION));   /* send cmd req */
  484.    while(ncb.cmdcplt == 0xff)       /* wait for recv */
  485.       ;
  486.    printf("command returned %d\n",ncmd.code);
  487. }
  488.  
  489. /*-------------------------------------------------------------------------*/
  490. cmd_bye(void)                                   /* shut down remote server */
  491. {
  492.    ACTION ncmd;
  493.    char buf[10];
  494.  
  495.    printf("Shut down remote server (y/n): ");
  496.    gets(buf);
  497.    if(toupper(*buf) == 'Y')
  498.    {
  499.       ncmd.type = NET_BYE;
  500.       ncmd.code = 0;
  501.       send_datagram(remote, &ncmd, sizeof(ACTION));
  502.       exitflag = 1;     /* force this program to exit too */
  503.    }
  504. }
  505.  
  506. /*-------------------------------------------------------------------------*/
  507. shell(int ac, char **av)          /* shell out one command and return */
  508. {
  509.    char *cmd;
  510.    int i;
  511.  
  512.    cmd = getenv("COMSPEC");
  513.  
  514.    if(*av[0])        /* something appears after the !... */
  515.    {
  516.       ac += 2;    /* so fill in command args */
  517.       for(i = ac - 1; i >= 2; i--)
  518.          av[i] = av[i - 2];
  519.       av[0] = cmd;      /* 1st arg is command.com pathname */
  520.       av[1] = "/C";     /* 2nd arg is /C (transient command) */
  521.       av[ac] = 0;    /* terminate parameter list */
  522.    }
  523.    else           /* otherwise shell out until exit */
  524.    {
  525.       av[0] = cmd;
  526.       av[1] = 0;
  527.       printf("EXIT to return to Tnet\n"); /* remind user */
  528.    }
  529.  
  530.    spawnv(P_WAIT, cmd, av);
  531. }
  532.  
  533. /*-------------------------------------------------------------------------*/
  534. cmd_help()                                         /* help screen */
  535. {
  536.    printf(  "\n"
  537.          "      Commands to remote server:\n"
  538.          "              get <filename>\n"
  539.          "              put <filename>\n"
  540.          "              cd  <dirname>\n"
  541.          "              dir <filename>\n"
  542.          "              del <filename>\n"
  543.          "              erase <filename>\n"
  544.          "              kill\n"
  545.          "\n"
  546.          "      Local commands:\n"
  547.          "              !<command>\n"
  548.          "              help\n"
  549.          "              quit\n"
  550.          "\n"
  551.          "      <filename> may contain wildcards\n"
  552.          "\n");
  553. }
  554.